package com.blensmile.utils;

import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.text.TextUtils;

import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by Blensmile on 2016/12/26.
 */
public  class MediaPlayerHelper implements AutoMediaPlayer.OnAudioMediaPlayerFoucusChanged{
    private static final ReentrantLock lock = new ReentrantLock();
    public static String mPlayingUrl = "";
    //only one need to play at a time
    private static MediaPlayer mPlayer;
    //record the previous played object's callBack
    private static CallBack mLastCallBack;
    private CallBack mCallBack;

    public MediaPlayerHelper(CallBack back) {
        this.mCallBack = back;
    }

    private boolean getPlayer(Context context, String url){
        if(lock.isLocked()){
            return false;
        }
        lock.lock();
        LogUtils.b(android.os.Process.myTid()+" locked");
        try {
            releasePlayer();
            registerCallBack(mCallBack);
            mPlayer = new AutoMediaPlayer(this);
            return true;
        }catch (Exception e){
            e.printStackTrace();
            releasePlayer();
            return false;
        }finally {
            if(lock.isLocked()) {
                LogUtils.b(android.os.Process.myTid()+" unlock");
                lock.unlock();
            }
        }
    }

    public void registerCallBack(){
        registerCallBack(mCallBack);
    }

    public static void registerCallBack(CallBack callBack){
        mLastCallBack = callBack;
    }

    public static void stopAndRelease(){
        releasePlayer();
    }

    /**
     *  releasePresent player
     */
    private static synchronized void releasePlayer(){
        mPlayingUrl = "";
        if (null != mLastCallBack) {
            mLastCallBack.onStop();
            mLastCallBack = null;
        }
        if(null!=mPlayer) {
            final AutoMediaPlayer releasePlayer = (AutoMediaPlayer)mPlayer;
            LogUtils.e("Created","id:" + releasePlayer.hashCode());
            mPlayer = null;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Thread.yield();
                    try {
                        if(isPlaying()) {
                            releasePlayer.stop();
                        }
                        releasePlayer.release();
                        LogUtils.b("MediaPlayer Released");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }

    /**
     * Used to play url media files.
     * if the player is in use, it will be stopped and its callback funtions will be called
     * don't handle handle MediaPlayer's event in callBack, stop() & releasePresent() is called in this function
     *
     * @param context
     * @param url
     */
    public void play(Context context, String url) {
        try {
            if (context != null && !TextUtils.isEmpty(url)) {
                if(getPlayer(context,url) && mPlayer != null) {
                    mPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
                        @Override
                        public boolean onError(MediaPlayer player, int what, int extra) {
                            releasePlayer();
                            return true;
                        }
                    });
                    mPlayer.setAudioStreamType(android.media.AudioManager.STREAM_MUSIC);
                    AudioManager mgr = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
                    float volume = mgr.getStreamVolume(android.media.AudioManager.STREAM_MUSIC);
                    mPlayer.setVolume(volume, volume);
                    mPlayingUrl = url;
                    mPlayer.setDataSource(mPlayingUrl);
                    mPlayer.prepareAsync();
                    mPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                        @Override
                        public void onPrepared(MediaPlayer player) {
                            if (null != mLastCallBack) {
                                mLastCallBack.onPlay();
                                player.start();
                            }
                        }
                    });
                    mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                        public void onCompletion(MediaPlayer player) {
                            releasePlayer();
                        }
                    });
                    return;
                }
            }
            mCallBack.onErro();
        } catch (Exception e){
            e.printStackTrace();
            releasePlayer();
        }
    }


    /**
     * @return
     */
    public static boolean isPlaying() {
        try {
            return (null != mPlayer) && mPlayer.isPlaying();
        } catch (Exception e) {
            e.printStackTrace();
            stopAndRelease();
            return false;
        }
    }

    public boolean isRepetition() {
        return (mPlayer != null) && (mLastCallBack == mCallBack);
    }

    @Override
    public void onMediaFoucusChanged(int foucusChanged) {
        switch (foucusChanged){
            case android.media.AudioManager.AUDIOFOCUS_LOSS:
            case android.media.AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
            case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
                stopAndRelease();
                break;
        }
    }

    public interface CallBack {
        void onPlay();
        void onStop();
        void onErro();
    }
}
